package order

import (
	"context"

	"mall/common/utils/pointy"
	"mall/service/backend/api/internal/logic/order/util"
	"mall/service/backend/api/internal/svc"
	"mall/service/backend/api/internal/types"
	"mall/service/backend/common/errorx"
	"mall/service/backend/common/i18n"
	"mall/service/order/rpc/orderclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetOrderByIdLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetOrderByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetOrderByIdLogic {
	return &GetOrderByIdLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetOrderByIdLogic) GetOrderById(req *types.IDReq) (*types.OrderInfoResp, error) {
	if req.Id == 0 {
		return nil, errorx.NewInvalidArgumentError(i18n.ValidationError)
	}

	res, err := l.svcCtx.OrderRpc.BackendGetOrderById(l.ctx, &orderclient.OrderIdReq{
		Id:              req.Id,
		WithSkus:        pointy.GetPointer(uint32(1)),
		WithAddresses:   pointy.GetPointer(uint32(1)),
		WithAdjustments: pointy.GetPointer(uint32(1)),
		WithDiscounts:   pointy.GetPointer(uint32(1)),
		WithPayments:    pointy.GetPointer(uint32(1)),
		WithShipments:   pointy.GetPointer(uint32(1)),
		WithLogs:        pointy.GetPointer(uint32(1)),
	})
	if err != nil {
		return nil, err
	}

	var skus []*types.OrderSkuInfo
	if len(res.Skus) > 0 {
		for _, v := range res.Skus {
			productTypeText := util.GetProductTypeText(v.ProductType)
			skus = append(skus, &types.OrderSkuInfo{
				Id:             v.Id,
				OrderId:        v.OrderId,
				ProductCode:    v.ProductCode,
				SkuId:          v.SkuId,
				SkuCode:        v.SkuCode,
				Sku:            v.Sku,
				ImageId:        v.ImageId,
				ImageUrl:       v.ImageUrl,
				ProductId:      v.ProductId,
				EntryId:        v.EntryId,
				Title:          v.Title,
				Slug:           v.Slug,
				ProductType:    v.ProductType,
				TypeText:       productTypeText,
				BrandId:        v.BrandId,
				BrandTitle:     v.BrandTitle,
				BrandSlug:      v.BrandSlug,
				GemPrice:       v.GemPrice,
				RetailPrice:    v.RetailPrice,
				Quantity:       v.Quantity,
				Weight:         v.Weight,
				TradeState:     v.TradeState,
				Status:         v.Status,
				RefundAmount:   v.RefundAmount,
				RefundQuantity: v.RefundQuantity,
			})
		}
	}
	var addresses []*types.OrderAddressInfo
	if len(res.Addresses) > 0 {
		for _, v := range res.Addresses {
			addresses = append(addresses, &types.OrderAddressInfo{
				Id:         v.Id,
				OrderId:    v.OrderId,
				UserId:     v.UserId,
				Consignee:  v.Consignee,
				Mobile:     v.Mobile,
				Province:   v.Province,
				City:       v.City,
				District:   v.District,
				Address:    v.Address,
				PostalCode: v.PostalCode,
				RegionCode: v.RegionCode,
				Label:      v.Label,
			})
		}
	}
	var discounts []*types.OrderDiscountInfo
	if len(res.Discounts) > 0 {
		for _, v := range res.Discounts {
			discounts = append(discounts, &types.OrderDiscountInfo{
				Id:               v.Id,
				OrderId:          v.OrderId,
				SkuId:            v.SkuId,
				ProductId:        v.ProductId,
				Title:            v.Title,
				Slug:             v.Slug,
				ActivityId:       v.ActivityId,
				ActivityRuleId:   v.ActivityRuleId,
				CouponTemplateId: v.CouponTemplateId,
				CouponId:         v.CouponId,
				CouponAmount:     v.CouponAmount,
				ActivityAmount:   v.ActivityAmount,
				IntegralAmount:   v.IntegralAmount,
				DiscountAmount:   v.DiscountAmount,
				Integrals:        v.Integrals,
			})
		}
	}
	var adjustments []*types.OrderAdjustmentInfo
	if len(res.Adjustments) > 0 {
		for _, v := range res.Adjustments {
			adjustments = append(adjustments, &types.OrderAdjustmentInfo{
				Id:         v.Id,
				OrderId:    v.OrderId,
				Amount:     v.Amount,
				Memo:       v.Memo,
				Status:     v.Status,
				OperatedBy: v.OperatedBy,
				OperatedAt: v.OperatedAt,
			})
		}
	}
	var payments []*types.OrderPaymentInfo
	if len(res.Payments) > 0 {
		for _, v := range res.Payments {
			payments = append(payments, &types.OrderPaymentInfo{
				Id:      v.Id,
				OrderId: v.OrderId,
				No:      v.No,
				Amount:  v.Amount,
				Type:    v.Type,
				Name:    v.Name,
				Code:    v.Code,
				PaidAt:  v.PaidAt,
			})
		}
	}
	var shipments []*types.OrderShipmentInfo
	if len(res.Shipments) > 0 {
		for _, v := range res.Shipments {
			shipments = append(shipments, &types.OrderShipmentInfo{
				Id:        v.Id,
				OrderId:   v.OrderId,
				No:        v.No,
				Type:      v.Type,
				Name:      v.Name,
				Code:      v.Code,
				UpdatedAt: v.UpdatedAt,
			})
		}
	}
	var logs []*types.OrderOperateLogInfo
	if len(res.Logs) > 0 {
		for _, v := range res.Logs {
			logs = append(logs, &types.OrderOperateLogInfo{
				Id:         v.Id,
				OrderId:    v.OrderId,
				TradeState: v.TradeState,
				NewState:   v.NewState,
				Type:       v.Type,
				Name:       v.Name,
				Code:       v.Code,
				Status:     v.Status,
				Memo:       v.Memo,
				OperatedBy: v.OperatedBy,
				OperatedAt: v.OperatedAt,
			})
		}
	}

	var tradeStateText *string
	if res.TradeState != nil {
		tradeStateText = util.GetTradeStateText(res.TradeState)
	}
	var orderTypeText *string
	if res.OrderType != nil {
		orderTypeText = util.GetOrderTypeText(res.OrderType)
	}
	option := util.GetOptionByTradeState(res.TradeState)

	return &types.OrderInfoResp{
		BaseDataInfo: types.BaseDataInfo{
			Success: true,
			Msg:     l.svcCtx.Trans.Trans(l.ctx, i18n.Success),
		},
		Data: &types.OrderInfo{
			BaseIDInfo: types.BaseIDInfo{
				Id:         res.Id,
				CreatedAt:  res.CreatedAt,
				UpdatedAt:  res.UpdatedAt,
				DeletedAt:  res.DeletedAt,
				CanRemove:  option.CanRemove,
				CanRestore: option.CanRestore,
			},
			ParentId:        res.ParentId,
			UserId:          res.UserId,
			UserRank:        res.UserRank,
			Buyer:           res.Buyer,
			Sn:              res.Sn,
			OrderType:       res.OrderType,
			OrderTypeText:   orderTypeText,
			SourceType:      res.SourceType,
			Total:           res.Number,
			GemAmount:       res.GemAmount,
			RetailAmount:    res.RetailAmount,
			Freight:         res.Freight,
			DiscountAmount:  res.DiscountAmount,
			AdjustAmount:    res.AdjustAmount,
			ActualAmount:    res.ActualAmount,
			BalanceAmount:   res.BalanceAmount,
			RefundAmount:    res.RefundAmount,
			Gems:            res.Gems,
			TradeState:      res.TradeState,
			TradeStateText:  tradeStateText,
			Remark:          res.Remark,
			SellerMemo:      res.SellerMemo,
			PaidAt:          res.PaidAt,
			ShippedAt:       res.ShippedAt,
			DeliveredAt:     res.DeliveredAt,
			ConfirmedAt:     res.ConfirmedAt,
			ReviewedAt:      res.ReviewedAt,
			FulfilledAt:     res.FulfilledAt,
			ClosedAt:        res.ClosedAt,
			AutoComfirmDays: res.AutoComfirmDays,
			Growth:          res.Growth,
			Integrals:       res.Integrals,
			CanAdjust:       option.CanAdjust,

			Skus:        skus,
			Addresses:   addresses,
			Discounts:   discounts,
			Adjustments: adjustments,
			Payments:    payments,
			Shipments:   shipments,
			Logs:        logs,
		},
	}, nil
}
